<script lang="ts" setup>
import type { VxeGridListeners, VxeGridProps } from '#/adapter/vxe-table';
import { h, ref } from 'vue';
import { MdiDelete } from '@vben/icons';
import { useVbenDrawer } from '@vben/common-ui';
import { useVbenVxeGrid } from '#/adapter/vxe-table';
import { Button, message } from 'ant-design-vue';
import { Description, useDescription } from '#/components';
import { updateReportdataApi, getSampleDataApi } from '#/api';
import { confirmModal } from '#/components';
import { type gridRowType, reportGridArr } from './schemas/data';

interface descSchemaProps {
  sampleName: string;
  sampleNo: string;
  modelSpec: string;
  testItems: string;
  reportNo: string;
}
const record = ref(); // 记录调用modal时传递过来的数据
const gridApi = ref(); // 记录调用时传递过来表格实例

const [register, descMethods] = useDescription({
  title: '样品信息',
  showTitle: false,
  colon: true,
  size: 'default',
  bordered: true,
  column: { md: 2, sm: 1, xs: 1 },
  schema: [
    { label: '样品名称', fieldName: 'sampleName' },
    { label: '样品编号', fieldName: 'sampleNo' },
    { label: '样品规格', fieldName: 'modelSpec' },
    { label: '测试项目', fieldName: 'testItems' },
    {
      label: '报告编号',
      fieldName: 'reportNo',
      render: (value: string) => {
        return h('span', { style: { color: 'orange', 'font-weight': 'bold' } }, value);
      },
    },
  ],
  labelStyle: { width: '150px', textAlign: 'right' },
});

const dataGridEvents: VxeGridListeners<gridRowType> = {
  editClosed: ({ row }) => {
    if (!row.standard || !row.tResult || row.standard === '/') return;
    if (!row.tResult.match(/^([<>≤≥]?\d+(\.\d+)?|未检出)$/)) return;
    if (row.tResult === '未检出') {
      row.tConc = '合格';
    } else {
      try {
        // 当测试结果完全匹配技术要求时
        if (row.tResult === row.standard.replace(/\s/g, '')) {
          row.tConc = '合格';
        } else if (isSubset(row.standard, row.tResult)) {
          row.tConc = '合格';
        } else {
          row.tConc = '不合格';
        }
      } catch (error) {
        row.tConc = null;
      }
    }
  },
};
const [dataGrid, dataGridApi] = useVbenVxeGrid({
  gridEvents: dataGridEvents, // 传递事件配置
  gridOptions: {
    border: true,
    autoResize: true,
    keepSource: true, // 是否保留源数据，用于重置表格
    showOverflow: false,
    rowConfig: { isHover: true },
    columns: [
      { type: 'seq', title: '序号', width: 80, dragSort: true },
      { field: 'tItem', title: '检测项目', minWidth: 200, slots: { default: 'detectionItemSlots' } },
      { field: 'tLimit', title: '检出限', minWidth: 100 },
      { field: 'standard', title: '技术要求', minWidth: 100 },
      { field: 'tResult', title: '检测结果', minWidth: 100, editRender: { name: 'input', enable: true } },
      { field: 'tConc', title: '单项结论', minWidth: 100, slots: { default: 'testConclusionSlots' } },
      { field: 'testMethod', title: '检测方法', minWidth: 180 },
      { fixed: 'right', title: '操作', width: 70, visible: true, slots: { edit: 'cellstool', default: 'cellstool' } },
    ],
    data: [],
    pagerConfig: { enabled: false },
    sortConfig: { multiple: true },
    validConfig: { msgMode: 'full' }, //验证时为同时多个错误提示模式
    editConfig: {
      mode: 'cell',
      trigger: 'click',
      showIcon: false,
    },
    editRules: {
      tItem: [{ required: true, message: '请输入检测项目' }],
      tLimit: [{ required: true, message: '请输入检测限' }],
      standard: [{ required: true, message: '请输入技术要求' }],
      tResult: [
        // 正则表达式校验，只能包含数字和-，且-不能在开头或结尾，也不能连续出现
        { required: true, pattern: /^([<>≤≥]?\d+(\.\d+)?|未检出)$/, message: '输入格式有误' },
      ],
      tConc: [{ required: true, message: '请输入单项结论' }],
      testMethod: [{ required: true, message: '请输入检测方法' }],
    },
  } as VxeGridProps<gridRowType>,
});

/* 通过抽屉方式加载当前内容 */
const [VbenDrawer, drawerApi] = useVbenDrawer({
  // fullscreen: true,  // 默认全屏
  confirmText: '提交',
  draggable: true,
  closeOnPressEscape: false,
  closeOnClickModal: false,

  async onOpenChange(isOpen) {
    // 判断是打开还是关闭
    if (!isOpen) return;
    record.value = drawerApi.getData().record || {};
    gridApi.value = drawerApi.getData().gridApi || null;

    if (!record.value?.sampleNo) {
      message.error('未传递有效数据！');
      drawerApi.setState({ showConfirmButton: false });
    }
    // 加载数据
    try {
      // 填充样品信息
      await loadDrawerData(record.value?.sampleNo)
        .then((res) => {
          descMethods.setDescProps({ data: res.descData });
          dataGridApi.grid.loadData(res.gridData);
          // 延迟0.5秒
          setTimeout(() => {}, 500);
        })
        .catch((error) => {
          throw new Error(error.message);
        });
    } catch (error) {
      message.error('初始化失败：' + error.message);
      drawerApi.setState({ showConfirmButton: false });
    }
  },
  // onOpened() {
  //   // 打开时再赋值，确保组件已经渲染完成
  // },
  onConfirm() {
    return onSubmit();
  },
  onCancel() {
    drawerApi.close();
  },
});

/*==============================函数过程===============================*/
/** 加载抽屉数据
 * @param sampleNo 样品编号
 * @returns {descData: object, gridData: array}
 */
async function loadDrawerData(sampleNo: string): Promise<{ descData: descSchemaProps; gridData: gridRowType[] }> {
  try {
    const res = await getSampleDataApi(sampleNo);

    // 加载表格数据
    const reportType = JSON.parse(res[0].sampleName).join('-');
    const reportTemplate = res[0].reportTable ? JSON.parse(res[0].reportTable) : reportGridArr[reportType];

    return {
      descData: { ...record.value },
      gridData: reportTemplate,
    };
  } catch (error) {
    throw new Error('加载数据失败(' + error.message + ')');
  }
}

async function ValidGrid() {
  // 获取表格行数
  const rowCount = dataGridApi.grid.getTableData().fullData.length;
  if (rowCount === 0) {
    return false;
  }
  const errMap = await dataGridApi.grid.fullValidate(true);
  // 验证结果：验证通过返回undefined（!errMap=true)，验证不通过返回一个对象(!errMap=false);
  if (!!errMap) {
    return '表格信息不完整！';
  }
  return !errMap;
}

// 解析条件字符串，返回运算符和数值
const parseCondition = (str: string): { operator: string; value: string } => {
  const firstChar = str.charAt(0); // 获取第一个字符
  if (['<', '>', '≤', '≥'].includes(firstChar)) {
    return {
      operator: firstChar,
      value: str.slice(1), // 截取第一个字符后的字符串
    };
  } else {
    return {
      operator: '=',
      value: str,
    };
  }
};

// 判断测试结果是否满足标准要求
const isSubset = (standard: string, testResult: string): boolean => {
  const { operator: opA, value: valA } = parseCondition(standard.replace(/\s/g, ''));
  const { operator: opB, value: valB } = parseCondition(testResult.replace(/\s/g, ''));

  const numA = parseFloat(valA);
  const numB = parseFloat(valB);

  // 标准是下界条件（> 或 ≥）
  if (opA === '>' || opA === '≥') {
    if (opB === '<' || opB === '≤') return false; // 上下界冲突

    if (opA === '≥') {
      // 标准是≥：要求测试结果值≥numA
      return numB >= numA;
    } else {
      // 标准是>：要求测试结果值>numA
      if (numB > numA) return true;
      if (numB === numA) {
        // 相等时要求测试结果必须是>(开区间)
        return opB === '>';
      }
      return false;
    }
  }
  // 标准是上界条件（< 或 ≤）
  else if (opA === '<' || opA === '≤') {
    if (opB === '>' || opB === '≥') return false; // 上下界冲突

    if (opA === '≤') {
      // 标准是≤：要求测试结果值≤numA
      return numB <= numA;
    } else {
      // 标准是<：要求测试结果值<numA
      if (numB < numA) return true;
      if (numB === numA) {
        // 相等时要求测试结果必须是<(开区间)
        return opB === '<';
      }
      return false;
    }
  }

  return false;
};

/*==============================表单事件===============================*/
async function onSubmit() {
  // 验证表单
  const isValid = await ValidGrid();
  if (isValid !== true) {
    message.error({ content: '数据填写不完整，请检查！', key: 'beforeSubmit' });
    return;
  }
  // 二次确认
  const confirmRes = await confirmModal('提交确认', '即将提交数据，是否继续？');
  if (!confirmRes) return;

  try {
    // 锁定modal
    drawerApi.lock();
    message.loading({
      content: '数据验证中，请稍后...',
      duration: 0,
      key: 'beforeSubmit',
    });

    const values = dataGridApi.grid.getTableData().fullData;
    await updateReportdataApi({
      sampleNo: record.value.sampleNo,
      sampleName: record.value.sampleName,
      data: JSON.stringify(values),
    }).then(() => {
      message.success({ content: '提交成功', key: 'beforeSubmit', duration: 2 });
      gridApi.value?.query();
      drawerApi.close();
    });
  } catch (error) {
    message.error({
      content: `提交失败：${error.message}`,
      key: 'beforeSubmit',
    });
  } finally {
    drawerApi.unlock();
  }
}

function handleRemove(row: gridRowType) {
  dataGridApi.grid.remove(row);
}

/*==============================其他事件===============================*/
</script>

<template>
  <VbenDrawer class="w-auto h-auto" title="测试数据登记">
    <Description @register="register" class="my-4 px-2" />
    <dataGrid>
      <template #detectionItemSlots="{ row }">
        <div v-html="row.tItem"></div>
      </template>
      <template #testConclusionSlots="{ row }">
        <span :style="{ color: row.tConc === '合格' ? 'green' : row.tConc === '不合格' ? 'red' : 'gray' }">{{
          row.tConc
        }}</span>
      </template>
      <template #cellstool="{ row }">
        <Button type="link" @click="handleRemove(row)">
          <!-- 20像素大小的图标 -->
          <MdiDelete class="size-5" style="color: red" />
        </Button>
      </template>
    </dataGrid>
  </VbenDrawer>
</template>
